package com.alex.springbootdemo.database;


import com.alex.springbootdemo.enums.SettingKeysEnum;
import com.alex.springbootdemo.lock.LockService;
import com.alex.springbootdemo.lock.RedissonLock;
import com.alex.springbootdemo.model.pojo.SystemSettings;
import com.alex.springbootdemo.service.SystemSettingService;
import com.gitq.jedi.common.migration.MigrationHelper;
import com.google.common.collect.Maps;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Objects;

/**
 *
 */
@Service
@Slf4j
@AllArgsConstructor
public class DatabaseInitializer {

    private final LockService lockService;
    private final SystemSettingService systemSettingService;

    @EventListener
    @Order(1)
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @RedissonLock(prefixKey = "database", key = "migrator.lock.init")
    public void handleContextRefresh(ContextRefreshedEvent event) {
        //FIXME 20230626 调整为分布式锁注解 @RedissonLock
//        lockService.executeWithLock("migrator.lock.init", () -> {
//            run();
//            return 0;
//        });
        run();
    }

    private void upgrade() {
        if (isVersionMatch()) { // double check
            return;
        }
        SystemSettings settings = systemSettingService.getByKey(SettingKeysEnum.DATA_VERSION);
        String appVersion = MigrationHelper.getVersion(DatabaseMigrator.class);
        log.info("Data version mismatch, start migration from {} to {}.", settings.getSettingValue(), appVersion);
        MigrationHelper.migrate(settings.getSettingValue(), DatabaseMigrator.class, Maps.newHashMap());
        settings.setSettingValue(appVersion);
        systemSettingService.saveSetting(settings);
        log.info("Finished migrating data");
    }

    private boolean isVersionMatch() {
        SystemSettings setting = systemSettingService.getByKey(SettingKeysEnum.DATA_VERSION);
        String appVersion = MigrationHelper.getVersion(DatabaseMigrator.class);
        log.debug("Data version is {}, app version is {}", setting.getSettingValue(), appVersion);
        return Objects.equals(setting.getSettingValue(), appVersion);
    }

    private void run() {
        if (isVersionMatch()) {
            log.info("Data version match, no need upgrade");
            return;
        }
        upgrade();
    }

}
